home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / samba.idb / usr / samba / src / source / clientgen.c.z / clientgen.c
Encoding:
C/C++ Source or Header  |  1998-10-28  |  39.5 KB  |  1,560 lines

  1. /* 
  2.    Unix SMB/Netbios implementation.
  3.    Version 1.9.
  4.    SMB client generic functions
  5.    Copyright (C) Andrew Tridgell 1994-1998
  6.    
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifdef SYSLOG
  23. #undef SYSLOG
  24. #endif
  25.  
  26. #include "includes.h"
  27. #include "trans2.h"
  28.  
  29.  
  30. extern int DEBUGLEVEL;
  31.  
  32. /****************************************************************************
  33. setup basics in a outgoing packet
  34. ****************************************************************************/
  35. static void cli_setup_packet(struct cli_state *cli)
  36. {
  37.     SSVAL(cli->outbuf,smb_pid,cli->pid);
  38.     SSVAL(cli->outbuf,smb_uid,cli->uid);
  39.     SSVAL(cli->outbuf,smb_mid,cli->mid);
  40.     if (cli->protocol > PROTOCOL_CORE) {
  41.         SCVAL(cli->outbuf,smb_flg,0x8);
  42.         SSVAL(cli->outbuf,smb_flg2,0x1);
  43.     }
  44. }
  45.  
  46.  
  47. /****************************************************************************
  48.   send a SMB trans or trans2 request
  49.   ****************************************************************************/
  50. static BOOL cli_send_trans(struct cli_state *cli,
  51.                int trans, char *name, int fid, int flags,
  52.                char *data,char *param,uint16 *setup, int ldata,int lparam,
  53.                int lsetup,int mdata,int mparam,int msetup)
  54. {
  55.     int i;
  56.     int this_ldata,this_lparam;
  57.     int tot_data=0,tot_param=0;
  58.     char *outdata,*outparam;
  59.     char *p;
  60.  
  61.     this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
  62.     this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
  63.  
  64.     bzero(cli->outbuf,smb_size);
  65.     set_message(cli->outbuf,14+lsetup,0,True);
  66.     CVAL(cli->outbuf,smb_com) = trans;
  67.     SSVAL(cli->outbuf,smb_tid, cli->cnum);
  68.     cli_setup_packet(cli);
  69.  
  70.     outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
  71.     outdata = outparam+this_lparam;
  72.  
  73.     /* primary request */
  74.     SSVAL(cli->outbuf,smb_tpscnt,lparam);    /* tpscnt */
  75.     SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
  76.     SSVAL(cli->outbuf,smb_mprcnt,mparam);    /* mprcnt */
  77.     SSVAL(cli->outbuf,smb_mdrcnt,mdata);    /* mdrcnt */
  78.     SCVAL(cli->outbuf,smb_msrcnt,msetup);    /* msrcnt */
  79.     SSVAL(cli->outbuf,smb_flags,flags);    /* flags */
  80.     SIVAL(cli->outbuf,smb_timeout,0);        /* timeout */
  81.     SSVAL(cli->outbuf,smb_pscnt,this_lparam);    /* pscnt */
  82.     SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
  83.     SSVAL(cli->outbuf,smb_dscnt,this_ldata);    /* dscnt */
  84.     SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
  85.     SCVAL(cli->outbuf,smb_suwcnt,lsetup);    /* suwcnt */
  86.     for (i=0;i<lsetup;i++)        /* setup[] */
  87.         SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
  88.     p = smb_buf(cli->outbuf);
  89.     if (trans==SMBtrans) {
  90.         pstrcpy(p,name);            /* name[] */
  91.     } else {
  92.         *p++ = 0;  /* put in a null smb_name */
  93.         *p++ = 'D'; *p++ = ' ';    /* observed in OS/2 */
  94.     }
  95.     if (this_lparam)            /* param[] */
  96.         memcpy(outparam,param,this_lparam);
  97.     if (this_ldata)            /* data[] */
  98.         memcpy(outdata,data,this_ldata);
  99.     set_message(cli->outbuf,14+lsetup,        /* wcnt, bcc */
  100.             PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
  101.  
  102.     show_msg(cli->outbuf);
  103.     send_smb(cli->fd,cli->outbuf);
  104.  
  105.     if (this_ldata < ldata || this_lparam < lparam) {
  106.         /* receive interim response */
  107.         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout) || 
  108.             CVAL(cli->inbuf,smb_rcls) != 0) {
  109.             return(False);
  110.         }      
  111.  
  112.         tot_data = this_ldata;
  113.         tot_param = this_lparam;
  114.         
  115.         while (tot_data < ldata || tot_param < lparam)  {
  116.             this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
  117.             this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
  118.  
  119.             set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
  120.             CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
  121.             
  122.             outparam = smb_buf(cli->outbuf);
  123.             outdata = outparam+this_lparam;
  124.             
  125.             /* secondary request */
  126.             SSVAL(cli->outbuf,smb_tpscnt,lparam);    /* tpscnt */
  127.             SSVAL(cli->outbuf,smb_tdscnt,ldata);    /* tdscnt */
  128.             SSVAL(cli->outbuf,smb_spscnt,this_lparam);    /* pscnt */
  129.             SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
  130.             SSVAL(cli->outbuf,smb_spsdisp,tot_param);    /* psdisp */
  131.             SSVAL(cli->outbuf,smb_sdscnt,this_ldata);    /* dscnt */
  132.             SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
  133.             SSVAL(cli->outbuf,smb_sdsdisp,tot_data);    /* dsdisp */
  134.             if (trans==SMBtrans2)
  135.                 SSVALS(cli->outbuf,smb_sfid,fid);        /* fid */
  136.             if (this_lparam)            /* param[] */
  137.                 memcpy(outparam,param,this_lparam);
  138.             if (this_ldata)            /* data[] */
  139.                 memcpy(outdata,data,this_ldata);
  140.             set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
  141.                     PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
  142.             
  143.             show_msg(cli->outbuf);
  144.             send_smb(cli->fd,cli->outbuf);
  145.             
  146.             tot_data += this_ldata;
  147.             tot_param += this_lparam;
  148.         }
  149.     }
  150.  
  151.     return(True);
  152. }
  153.  
  154.  
  155. /****************************************************************************
  156.   receive a SMB trans or trans2 response allocating the necessary memory
  157.   ****************************************************************************/
  158. static BOOL cli_receive_trans(struct cli_state *cli,
  159.                   int trans,int *data_len,
  160.                   int *param_len, char **data,char **param)
  161. {
  162.     int total_data=0;
  163.     int total_param=0;
  164.     int this_data,this_param;
  165.     
  166.     *data_len = *param_len = 0;
  167.     
  168.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  169.         return False;
  170.  
  171.     show_msg(cli->inbuf);
  172.     
  173.     /* sanity check */
  174.     if (CVAL(cli->inbuf,smb_com) != trans) {
  175.         DEBUG(0,("Expected %s response, got command 0x%02x\n",
  176.              trans==SMBtrans?"SMBtrans":"SMBtrans2", 
  177.              CVAL(cli->inbuf,smb_com)));
  178.         return(False);
  179.     }
  180.     if (CVAL(cli->inbuf,smb_rcls) != 0)
  181.         return(False);
  182.  
  183.     /* parse out the lengths */
  184.     total_data = SVAL(cli->inbuf,smb_tdrcnt);
  185.     total_param = SVAL(cli->inbuf,smb_tprcnt);
  186.  
  187.     /* allocate it */
  188.     *data = Realloc(*data,total_data);
  189.     *param = Realloc(*param,total_param);
  190.  
  191.     while (1)  {
  192.         this_data = SVAL(cli->inbuf,smb_drcnt);
  193.         this_param = SVAL(cli->inbuf,smb_prcnt);
  194.  
  195.         if (this_data + *data_len > total_data ||
  196.             this_param + *param_len > total_param) {
  197.             DEBUG(1,("Data overflow in cli_receive_trans\n"));
  198.             return False;
  199.         }
  200.  
  201.         if (this_data)
  202.             memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
  203.                    smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
  204.                    this_data);
  205.         if (this_param)
  206.             memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
  207.                    smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
  208.                    this_param);
  209.         *data_len += this_data;
  210.         *param_len += this_param;
  211.  
  212.         /* parse out the total lengths again - they can shrink! */
  213.         total_data = SVAL(cli->inbuf,smb_tdrcnt);
  214.         total_param = SVAL(cli->inbuf,smb_tprcnt);
  215.         
  216.         if (total_data <= *data_len && total_param <= *param_len)
  217.             break;
  218.         
  219.         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  220.             return False;
  221.  
  222.         show_msg(cli->inbuf);
  223.         
  224.         /* sanity check */
  225.         if (CVAL(cli->inbuf,smb_com) != trans) {
  226.             DEBUG(0,("Expected %s response, got command 0x%02x\n",
  227.                  trans==SMBtrans?"SMBtrans":"SMBtrans2", 
  228.                  CVAL(cli->inbuf,smb_com)));
  229.             return(False);
  230.         }
  231.         if (CVAL(cli->inbuf,smb_rcls) != 0)
  232.             return(False);
  233.     }
  234.     
  235.     return(True);
  236. }
  237.  
  238.  
  239. /****************************************************************************
  240. call a remote api
  241. ****************************************************************************/
  242. static BOOL cli_api(struct cli_state *cli,
  243.             int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
  244.             int *rdrcnt, char *param,char *data, 
  245.             char **rparam, char **rdata)
  246. {
  247.   cli_send_trans(cli,SMBtrans,PIPE_LANMAN,0,0,
  248.          data,param,NULL,
  249.          drcnt,prcnt,0,
  250.          mdrcnt,mprcnt,0);
  251.  
  252.   return (cli_receive_trans(cli,SMBtrans,
  253.                      rdrcnt,rprcnt,
  254.                      rdata,rparam));
  255. }
  256.  
  257.  
  258. /****************************************************************************
  259. perform a NetWkstaUserLogon
  260. ****************************************************************************/
  261. BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
  262. {
  263.     char *rparam = NULL;
  264.     char *rdata = NULL;
  265.     char *p;
  266.     int rdrcnt,rprcnt;
  267.     pstring param;
  268.  
  269.     memset(param, 0, sizeof(param));
  270.     
  271.     /* send a SMBtrans command with api NetWkstaUserLogon */
  272.     p = param;
  273.     SSVAL(p,0,132); /* api number */
  274.     p += 2;
  275.     pstrcpy(p,"OOWb54WrLh");
  276.     p = skip_string(p,1);
  277.     pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
  278.     p = skip_string(p,1);
  279.     SSVAL(p,0,1);
  280.     p += 2;
  281.     pstrcpy(p,user);
  282.     strupper(p);
  283.     p += 21; p++; p += 15; p++; 
  284.     pstrcpy(p, workstation); 
  285.     strupper(p);
  286.     p += 16;
  287.     SSVAL(p, 0, BUFFER_SIZE);
  288.     p += 2;
  289.     SSVAL(p, 0, BUFFER_SIZE);
  290.     p += 2;
  291.     
  292.     cli->error = -1;
  293.     
  294.     if (cli_api(cli, PTR_DIFF(p,param),0,
  295.             1024,BUFFER_SIZE,
  296.             &rprcnt,&rdrcnt,
  297.             param,NULL,
  298.             &rparam,&rdata)) {
  299.         cli->error = SVAL(rparam,0);
  300.         p = rdata;
  301.         
  302.         if (cli->error == 0) {
  303.             DEBUG(4,("NetWkstaUserLogon success\n"));
  304.             cli->privilages = SVAL(p, 24);
  305.             fstrcpy(cli->eff_name,p+2);
  306.         } else {
  307.             DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->error));
  308.         }
  309.     }
  310.     
  311.     if (rparam) free(rparam);
  312.     if (rdata) free(rdata);
  313.     return cli->error == 0;
  314. }
  315.  
  316.  
  317. /****************************************************************************
  318. call a NetServerEnum for the specified workgroup and servertype mask.
  319. This function then calls the specified callback function for each name returned.
  320.  
  321. The callback function takes 3 arguments: the machine name, the server type and
  322. the comment.
  323. ****************************************************************************/
  324. BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
  325.                void (*fn)(char *, uint32, char *))
  326. {
  327.     char *rparam = NULL;
  328.     char *rdata = NULL;
  329.     int rdrcnt,rprcnt;
  330.     char *p;
  331.     pstring param;
  332.     int uLevel = 1;
  333.     int count = -1;
  334.   
  335.     /* send a SMBtrans command with api NetServerEnum */
  336.     p = param;
  337.     SSVAL(p,0,0x68); /* api number */
  338.     p += 2;
  339.     pstrcpy(p,"WrLehDz");
  340.     p = skip_string(p,1);
  341.   
  342.     pstrcpy(p,"B16BBDz");
  343.   
  344.     p = skip_string(p,1);
  345.     SSVAL(p,0,uLevel);
  346.     SSVAL(p,2,BUFFER_SIZE);
  347.     p += 4;
  348.     SIVAL(p,0,stype);
  349.     p += 4;
  350.     
  351.     pstrcpy(p, workgroup);
  352.     p = skip_string(p,1);
  353.     
  354.     if (cli_api(cli, 
  355.             PTR_DIFF(p,param), /* param count */
  356.             0, /*data count */
  357.             8, /* mprcount */
  358.             BUFFER_SIZE, /* mdrcount */
  359.             &rprcnt,&rdrcnt,
  360.             param, NULL, 
  361.             &rparam,&rdata)) {
  362.         int res = SVAL(rparam,0);
  363.         int converter=SVAL(rparam,2);
  364.         int i;
  365.             
  366.         if (res == 0) {
  367.             count=SVAL(rparam,4);
  368.             p = rdata;
  369.                     
  370.             for (i = 0;i < count;i++, p += 26) {
  371.                 char *sname = p;
  372.                 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
  373.                 char *cmnt = comment_offset?(rdata+comment_offset):"";
  374.                 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
  375.  
  376.                 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
  377.  
  378.                 fn(sname, stype, cmnt);
  379.             }
  380.         }
  381.     }
  382.   
  383.     if (rparam) free(rparam);
  384.     if (rdata) free(rdata);
  385.     
  386.     return(count > 0);
  387. }
  388.  
  389.  
  390.  
  391.  
  392. static  struct {
  393.     int prot;
  394.     char *name;
  395.   }
  396. prots[] = 
  397.     {
  398.       {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
  399.       {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
  400.       {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
  401.       {PROTOCOL_LANMAN1,"LANMAN1.0"},
  402.       {PROTOCOL_LANMAN2,"LM1.2X002"},
  403.       {PROTOCOL_LANMAN2,"Samba"},
  404.       {PROTOCOL_NT1,"NT LM 0.12"},
  405.       {PROTOCOL_NT1,"NT LANMAN 1.0"},
  406.       {-1,NULL}
  407.     };
  408.  
  409.  
  410. /****************************************************************************
  411. send a session setup
  412. ****************************************************************************/
  413. BOOL cli_session_setup(struct cli_state *cli, 
  414.                char *user, 
  415.                char *pass, int passlen,
  416.                char *ntpass, int ntpasslen,
  417.                char *workgroup)
  418. {
  419.     char *p;
  420.     fstring pword;
  421.  
  422.     if (cli->protocol < PROTOCOL_LANMAN1)
  423.         return True;
  424.  
  425.     if (passlen > sizeof(pword)-1) {
  426.         return False;
  427.     }
  428.  
  429.         if(((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
  430.           /* Null session connect. */
  431.           pword[0] = '\0';
  432.         } else {
  433.           if ((cli->sec_mode & 2) && passlen != 24) {
  434.             passlen = 24;
  435.             SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
  436.           } else {
  437.             memcpy(pword, pass, passlen);
  438.           }
  439.         }
  440.  
  441.     /* if in share level security then don't send a password now */
  442.     if (!(cli->sec_mode & 1)) {fstrcpy(pword, "");passlen=1;} 
  443.  
  444.     /* send a session setup command */
  445.     bzero(cli->outbuf,smb_size);
  446.  
  447.     if (cli->protocol < PROTOCOL_NT1) {
  448.         set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
  449.         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
  450.         cli_setup_packet(cli);
  451.  
  452.         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  453.         SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
  454.         SSVAL(cli->outbuf,smb_vwv3,2);
  455.         SSVAL(cli->outbuf,smb_vwv4,1);
  456.         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
  457.         SSVAL(cli->outbuf,smb_vwv7,passlen);
  458.         p = smb_buf(cli->outbuf);
  459.         memcpy(p,pword,passlen);
  460.         p += passlen;
  461.         pstrcpy(p,user);
  462.         strupper(p);
  463.     } else {
  464.         set_message(cli->outbuf,13,0,True);
  465.         CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
  466.         cli_setup_packet(cli);
  467.         
  468.         CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  469.         SSVAL(cli->outbuf,smb_vwv2,BUFFER_SIZE);
  470.         SSVAL(cli->outbuf,smb_vwv3,2);
  471.         SSVAL(cli->outbuf,smb_vwv4,cli->pid);
  472.         SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
  473.         SSVAL(cli->outbuf,smb_vwv7,passlen);
  474.         SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
  475.         p = smb_buf(cli->outbuf);
  476.         memcpy(p,pword,passlen); 
  477.         p += SVAL(cli->outbuf,smb_vwv7);
  478.         memcpy(p,ntpass,ntpasslen); 
  479.         p += SVAL(cli->outbuf,smb_vwv8);
  480.         pstrcpy(p,user);
  481.         strupper(p);
  482.         p = skip_string(p,1);
  483.         pstrcpy(p,workgroup);
  484.         strupper(p);
  485.         p = skip_string(p,1);
  486.         pstrcpy(p,"Unix");p = skip_string(p,1);
  487.         pstrcpy(p,"Samba");p = skip_string(p,1);
  488.         set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
  489.     }
  490.  
  491.       send_smb(cli->fd,cli->outbuf);
  492.       if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  493.           return False;
  494.  
  495.       show_msg(cli->inbuf);
  496.  
  497.       if (CVAL(cli->inbuf,smb_rcls) != 0) {
  498.           return False;
  499.       }
  500.  
  501.       /* use the returned uid from now on */
  502.       cli->uid = SVAL(cli->inbuf,smb_uid);
  503.  
  504.       return True;
  505. }
  506.  
  507. /****************************************************************************
  508.  Send a uloggoff.
  509. *****************************************************************************/
  510.  
  511. BOOL cli_ulogoff(struct cli_state *cli)
  512. {
  513.         bzero(cli->outbuf,smb_size);
  514.         set_message(cli->outbuf,2,0,True);
  515.         CVAL(cli->outbuf,smb_com) = SMBulogoffX;
  516.         cli_setup_packet(cli);
  517.         SSVAL(cli->outbuf,smb_vwv0,0xFF);
  518.         SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
  519.  
  520.         send_smb(cli->fd,cli->outbuf);
  521.         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  522.                 return False;
  523.  
  524.         return CVAL(cli->inbuf,smb_rcls) == 0;
  525. }
  526.  
  527. /****************************************************************************
  528. send a tconX
  529. ****************************************************************************/
  530. BOOL cli_send_tconX(struct cli_state *cli, 
  531.             char *share, char *dev, char *pass, int passlen)
  532. {
  533.     fstring fullshare, pword;
  534.     char *p;
  535.     bzero(cli->outbuf,smb_size);
  536.     bzero(cli->inbuf,smb_size);
  537.  
  538.     if (cli->sec_mode & 1) {
  539.         passlen = 1;
  540.         pass = "";
  541.     }
  542.  
  543.     if ((cli->sec_mode & 2) && *pass && passlen != 24) {
  544.         passlen = 24;
  545.         SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
  546.     } else {
  547.         memcpy(pword, pass, passlen);
  548.     }
  549.  
  550.     slprintf(fullshare, sizeof(fullshare)-1,
  551.          "\\\\%s\\%s", cli->desthost, share);
  552.  
  553.     set_message(cli->outbuf,4,
  554.             2 + strlen(fullshare) + passlen + strlen(dev),True);
  555.     CVAL(cli->outbuf,smb_com) = SMBtconX;
  556.     cli_setup_packet(cli);
  557.  
  558.     SSVAL(cli->outbuf,smb_vwv0,0xFF);
  559.     SSVAL(cli->outbuf,smb_vwv3,passlen);
  560.  
  561.     p = smb_buf(cli->outbuf);
  562.     memcpy(p,pword,passlen);
  563.     p += passlen;
  564.     pstrcpy(p,fullshare);
  565.     p = skip_string(p,1);
  566.     pstrcpy(p,dev);
  567.  
  568.     SCVAL(cli->inbuf,smb_rcls, 1);
  569.  
  570.     send_smb(cli->fd,cli->outbuf);
  571.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  572.         return False;
  573.  
  574.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  575.         return False;
  576.     }
  577.  
  578.     cli->cnum = SVAL(cli->inbuf,smb_tid);
  579.     return True;
  580. }
  581.  
  582.  
  583. /****************************************************************************
  584. send a tree disconnect
  585. ****************************************************************************/
  586. BOOL cli_tdis(struct cli_state *cli)
  587. {
  588.     bzero(cli->outbuf,smb_size);
  589.     set_message(cli->outbuf,0,0,True);
  590.     CVAL(cli->outbuf,smb_com) = SMBtdis;
  591.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  592.     cli_setup_packet(cli);
  593.     
  594.     send_smb(cli->fd,cli->outbuf);
  595.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  596.         return False;
  597.     
  598.     return CVAL(cli->inbuf,smb_rcls) == 0;
  599. }
  600.  
  601. /****************************************************************************
  602. rename a file
  603. ****************************************************************************/
  604. BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst)
  605. {
  606.         char *p;
  607.  
  608.         bzero(cli->outbuf,smb_size);
  609.         bzero(cli->inbuf,smb_size);
  610.  
  611.         set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
  612.  
  613.         CVAL(cli->outbuf,smb_com) = SMBmv;
  614.         SSVAL(cli->outbuf,smb_tid,cli->cnum);
  615.         cli_setup_packet(cli);
  616.  
  617.         SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
  618.  
  619.         p = smb_buf(cli->outbuf);
  620.         *p++ = 4;
  621.         pstrcpy(p,fname_src);
  622.         p = skip_string(p,1);
  623.         *p++ = 4;
  624.         pstrcpy(p,fname_dst);
  625.  
  626.         send_smb(cli->fd,cli->outbuf);
  627.         if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  628.                 return False;
  629.         }
  630.  
  631.         if (CVAL(cli->inbuf,smb_rcls) != 0) {
  632.                 return False;
  633.         }
  634.  
  635.         return True;
  636. }
  637.  
  638. /****************************************************************************
  639. delete a file
  640. ****************************************************************************/
  641. BOOL cli_unlink(struct cli_state *cli, char *fname)
  642. {
  643.     char *p;
  644.  
  645.     bzero(cli->outbuf,smb_size);
  646.     bzero(cli->inbuf,smb_size);
  647.  
  648.     set_message(cli->outbuf,1, 2 + strlen(fname),True);
  649.  
  650.     CVAL(cli->outbuf,smb_com) = SMBunlink;
  651.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  652.     cli_setup_packet(cli);
  653.  
  654.     SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
  655.   
  656.     p = smb_buf(cli->outbuf);
  657.     *p++ = 4;      
  658.     pstrcpy(p,fname);
  659.  
  660.     send_smb(cli->fd,cli->outbuf);
  661.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  662.         return False;
  663.     }
  664.  
  665.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  666.         return False;
  667.     }
  668.  
  669.     return True;
  670. }
  671.  
  672.  
  673. /****************************************************************************
  674. create a directory
  675. ****************************************************************************/
  676. BOOL cli_mkdir(struct cli_state *cli, char *dname)
  677. {
  678.     char *p;
  679.  
  680.     bzero(cli->outbuf,smb_size);
  681.     bzero(cli->inbuf,smb_size);
  682.  
  683.     set_message(cli->outbuf,0, 2 + strlen(dname),True);
  684.  
  685.     CVAL(cli->outbuf,smb_com) = SMBmkdir;
  686.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  687.     cli_setup_packet(cli);
  688.  
  689.     p = smb_buf(cli->outbuf);
  690.     *p++ = 4;      
  691.     pstrcpy(p,dname);
  692.  
  693.     send_smb(cli->fd,cli->outbuf);
  694.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  695.         return False;
  696.     }
  697.  
  698.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  699.         return False;
  700.     }
  701.  
  702.     return True;
  703. }
  704.  
  705. /****************************************************************************
  706. remove a directory
  707. ****************************************************************************/
  708. BOOL cli_rmdir(struct cli_state *cli, char *dname)
  709. {
  710.     char *p;
  711.  
  712.     bzero(cli->outbuf,smb_size);
  713.     bzero(cli->inbuf,smb_size);
  714.  
  715.     set_message(cli->outbuf,0, 2 + strlen(dname),True);
  716.  
  717.     CVAL(cli->outbuf,smb_com) = SMBrmdir;
  718.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  719.     cli_setup_packet(cli);
  720.  
  721.     p = smb_buf(cli->outbuf);
  722.     *p++ = 4;      
  723.     pstrcpy(p,dname);
  724.  
  725.     send_smb(cli->fd,cli->outbuf);
  726.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  727.         return False;
  728.     }
  729.  
  730.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  731.         return False;
  732.     }
  733.  
  734.     return True;
  735. }
  736.  
  737.  
  738.  
  739. /****************************************************************************
  740. open a file
  741. ****************************************************************************/
  742. int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
  743. {
  744.     char *p;
  745.     unsigned openfn=0;
  746.     unsigned accessmode=0;
  747.  
  748.     if (flags & O_CREAT)
  749.         openfn |= (1<<4);
  750.     if (!(flags & O_EXCL)) {
  751.         if (flags & O_TRUNC)
  752.             openfn |= (1<<1);
  753.         else
  754.             openfn |= (1<<0);
  755.     }
  756.  
  757.     accessmode = (share_mode<<4);
  758.  
  759.     if ((flags & O_RDWR) == O_RDWR) {
  760.         accessmode |= 2;
  761.     } else if ((flags & O_WRONLY) == O_WRONLY) {
  762.         accessmode |= 1;
  763.     } 
  764.  
  765. #if defined(O_SYNC)
  766.     if ((flags & O_SYNC) == O_SYNC) {
  767.         accessmode |= (1<<14);
  768.     }
  769. #endif /* O_SYNC */
  770.  
  771.     bzero(cli->outbuf,smb_size);
  772.     bzero(cli->inbuf,smb_size);
  773.  
  774.     set_message(cli->outbuf,15,1 + strlen(fname),True);
  775.  
  776.     CVAL(cli->outbuf,smb_com) = SMBopenX;
  777.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  778.     cli_setup_packet(cli);
  779.  
  780.     SSVAL(cli->outbuf,smb_vwv0,0xFF);
  781.     SSVAL(cli->outbuf,smb_vwv2,0);  /* no additional info */
  782.     SSVAL(cli->outbuf,smb_vwv3,accessmode);
  783.     SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
  784.     SSVAL(cli->outbuf,smb_vwv5,0);
  785.     SSVAL(cli->outbuf,smb_vwv8,openfn);
  786.   
  787.     p = smb_buf(cli->outbuf);
  788.     pstrcpy(p,fname);
  789.     p = skip_string(p,1);
  790.  
  791.     send_smb(cli->fd,cli->outbuf);
  792.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  793.         return -1;
  794.     }
  795.  
  796.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  797.         return -1;
  798.     }
  799.  
  800.     return SVAL(cli->inbuf,smb_vwv2);
  801. }
  802.  
  803.  
  804.  
  805.  
  806. /****************************************************************************
  807.   close a file
  808. ****************************************************************************/
  809. BOOL cli_close(struct cli_state *cli, int fnum)
  810. {
  811.     bzero(cli->outbuf,smb_size);
  812.     bzero(cli->inbuf,smb_size);
  813.  
  814.     set_message(cli->outbuf,3,0,True);
  815.  
  816.     CVAL(cli->outbuf,smb_com) = SMBclose;
  817.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  818.     cli_setup_packet(cli);
  819.  
  820.     SSVAL(cli->outbuf,smb_vwv0,fnum);
  821.     SIVALS(cli->outbuf,smb_vwv1,-1);
  822.  
  823.     send_smb(cli->fd,cli->outbuf);
  824.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  825.         return False;
  826.     }
  827.  
  828.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  829.         return False;
  830.     }
  831.  
  832.     return True;
  833. }
  834.  
  835.  
  836. /****************************************************************************
  837.   lock a file
  838. ****************************************************************************/
  839. BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
  840. {
  841.     char *p;
  842.  
  843.     bzero(cli->outbuf,smb_size);
  844.     bzero(cli->inbuf,smb_size);
  845.  
  846.     set_message(cli->outbuf,8,10,True);
  847.  
  848.     CVAL(cli->outbuf,smb_com) = SMBlockingX;
  849.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  850.     cli_setup_packet(cli);
  851.  
  852.     CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  853.     SSVAL(cli->outbuf,smb_vwv2,fnum);
  854.     CVAL(cli->outbuf,smb_vwv3) = 0;
  855.     SIVALS(cli->outbuf, smb_vwv4, timeout);
  856.     SSVAL(cli->outbuf,smb_vwv6,0);
  857.     SSVAL(cli->outbuf,smb_vwv7,1);
  858.  
  859.     p = smb_buf(cli->outbuf);
  860.     SSVAL(p, 0, cli->pid);
  861.     SIVAL(p, 2, offset);
  862.     SIVAL(p, 6, len);
  863.  
  864.     send_smb(cli->fd,cli->outbuf);
  865.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  866.         return False;
  867.     }
  868.  
  869.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  870.         return False;
  871.     }
  872.  
  873.     return True;
  874. }
  875.  
  876. /****************************************************************************
  877.   unlock a file
  878. ****************************************************************************/
  879. BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
  880. {
  881.     char *p;
  882.  
  883.     bzero(cli->outbuf,smb_size);
  884.     bzero(cli->inbuf,smb_size);
  885.  
  886.     set_message(cli->outbuf,8,10,True);
  887.  
  888.     CVAL(cli->outbuf,smb_com) = SMBlockingX;
  889.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  890.     cli_setup_packet(cli);
  891.  
  892.     CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  893.     SSVAL(cli->outbuf,smb_vwv2,fnum);
  894.     CVAL(cli->outbuf,smb_vwv3) = 0;
  895.     SIVALS(cli->outbuf, smb_vwv4, timeout);
  896.     SSVAL(cli->outbuf,smb_vwv6,1);
  897.     SSVAL(cli->outbuf,smb_vwv7,0);
  898.  
  899.     p = smb_buf(cli->outbuf);
  900.     SSVAL(p, 0, cli->pid);
  901.     SIVAL(p, 2, offset);
  902.     SIVAL(p, 6, len);
  903.  
  904.     send_smb(cli->fd,cli->outbuf);
  905.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  906.         return False;
  907.     }
  908.  
  909.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  910.         return False;
  911.     }
  912.  
  913.     return True;
  914. }
  915.  
  916.  
  917. /****************************************************************************
  918.   read from a file
  919. ****************************************************************************/
  920. int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
  921. {
  922.     char *p;
  923.  
  924.     bzero(cli->outbuf,smb_size);
  925.     bzero(cli->inbuf,smb_size);
  926.  
  927.     set_message(cli->outbuf,10,0,True);
  928.  
  929.     CVAL(cli->outbuf,smb_com) = SMBreadX;
  930.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  931.     cli_setup_packet(cli);
  932.  
  933.     CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  934.     SSVAL(cli->outbuf,smb_vwv2,fnum);
  935.     SIVAL(cli->outbuf,smb_vwv3,offset);
  936.     SSVAL(cli->outbuf,smb_vwv5,size);
  937.     SSVAL(cli->outbuf,smb_vwv6,size);
  938.  
  939.     send_smb(cli->fd,cli->outbuf);
  940.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  941.         return -1;
  942.     }
  943.  
  944.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  945.         return -1;
  946.     }
  947.  
  948.     size = SVAL(cli->inbuf, smb_vwv5);
  949.     p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
  950.  
  951.     memcpy(buf, p, size);
  952.  
  953.     return size;
  954. }
  955.  
  956.  
  957. /****************************************************************************
  958.   write to a file
  959. ****************************************************************************/
  960. int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
  961. {
  962.     char *p;
  963.  
  964.     bzero(cli->outbuf,smb_size);
  965.     bzero(cli->inbuf,smb_size);
  966.  
  967.     set_message(cli->outbuf,12,size,True);
  968.  
  969.     CVAL(cli->outbuf,smb_com) = SMBwriteX;
  970.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  971.     cli_setup_packet(cli);
  972.  
  973.     CVAL(cli->outbuf,smb_vwv0) = 0xFF;
  974.     SSVAL(cli->outbuf,smb_vwv2,fnum);
  975.     SIVAL(cli->outbuf,smb_vwv3,offset);
  976.  
  977.     SSVAL(cli->outbuf,smb_vwv10,size);
  978.     SSVAL(cli->outbuf,smb_vwv11,smb_buf(cli->outbuf) - smb_base(cli->outbuf));
  979.  
  980.     p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
  981.     memcpy(p, buf, size);
  982.  
  983.     send_smb(cli->fd,cli->outbuf);
  984.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  985.         return -1;
  986.     }
  987.  
  988.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  989.         return -1;
  990.     }
  991.  
  992.     return SVAL(cli->inbuf, smb_vwv2);
  993. }
  994.  
  995.  
  996. /****************************************************************************
  997. do a SMBgetatr call
  998. ****************************************************************************/
  999. BOOL cli_getatr(struct cli_state *cli, char *fname, 
  1000.         int *attr, uint32 *size, time_t *t)
  1001. {
  1002.     char *p;
  1003.  
  1004.     bzero(cli->outbuf,smb_size);
  1005.     bzero(cli->inbuf,smb_size);
  1006.  
  1007.     set_message(cli->outbuf,0,strlen(fname)+2,True);
  1008.  
  1009.     CVAL(cli->outbuf,smb_com) = SMBgetatr;
  1010.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  1011.     cli_setup_packet(cli);
  1012.  
  1013.     p = smb_buf(cli->outbuf);
  1014.     *p = 4;
  1015.     pstrcpy(p+1, fname);
  1016.  
  1017.     send_smb(cli->fd,cli->outbuf);
  1018.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  1019.         return False;
  1020.     }
  1021.     
  1022.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  1023.         return False;
  1024.     }
  1025.  
  1026.     if (size) {
  1027.         *size = IVAL(cli->inbuf, smb_vwv3);
  1028.     }
  1029.  
  1030.     if (t) {
  1031.         *t = make_unix_date3(cli->inbuf+smb_vwv1);
  1032.     }
  1033.  
  1034.     if (attr) {
  1035.         *attr = SVAL(cli->inbuf,smb_vwv0);
  1036.     }
  1037.  
  1038.  
  1039.     return True;
  1040. }
  1041.  
  1042.  
  1043. /****************************************************************************
  1044. do a SMBsetatr call
  1045. ****************************************************************************/
  1046. BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t)
  1047. {
  1048.     char *p;
  1049.  
  1050.     bzero(cli->outbuf,smb_size);
  1051.     bzero(cli->inbuf,smb_size);
  1052.  
  1053.     set_message(cli->outbuf,8,strlen(fname)+4,True);
  1054.  
  1055.     CVAL(cli->outbuf,smb_com) = SMBsetatr;
  1056.     SSVAL(cli->outbuf,smb_tid,cli->cnum);
  1057.     cli_setup_packet(cli);
  1058.  
  1059.     SSVAL(cli->outbuf,smb_vwv0, attr);
  1060.     put_dos_date3(cli->outbuf,smb_vwv1, t);
  1061.  
  1062.     p = smb_buf(cli->outbuf);
  1063.     *p = 4;
  1064.     pstrcpy(p+1, fname);
  1065.     p = skip_string(p,1);
  1066.     *p = 4;
  1067.  
  1068.     send_smb(cli->fd,cli->outbuf);
  1069.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
  1070.         return False;
  1071.     }
  1072.     
  1073.     if (CVAL(cli->inbuf,smb_rcls) != 0) {
  1074.         return False;
  1075.     }
  1076.  
  1077.     return True;
  1078. }
  1079.  
  1080. /****************************************************************************
  1081. send a qpathinfo call
  1082. ****************************************************************************/
  1083. BOOL cli_qpathinfo(struct cli_state *cli, char *fname, 
  1084.            time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
  1085. {
  1086.     int data_len = 0;
  1087.     int param_len = 0;
  1088.     uint16 setup = TRANSACT2_QPATHINFO;
  1089.     pstring param;
  1090.     char *rparam=NULL, *rdata=NULL;
  1091.  
  1092.     param_len = strlen(fname) + 7;
  1093.  
  1094.     memset(param, 0, param_len);
  1095.     SSVAL(param, 0, SMB_INFO_STANDARD);
  1096.     pstrcpy(¶m[6], fname);
  1097.  
  1098.     if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
  1099.                 NULL, param, &setup, 
  1100.                 data_len, param_len, 1,
  1101.                 cli->max_xmit, 10, 0)) {
  1102.         return False;
  1103.     }
  1104.  
  1105.     if (!cli_receive_trans(cli, SMBtrans2, &data_len, ¶m_len, 
  1106.                    &rdata, &rparam)) {
  1107.         return False;
  1108.     }
  1109.  
  1110.     if (!rdata || data_len < 22) {
  1111.         return False;
  1112.     }
  1113.  
  1114.     if (c_time) {
  1115.         *c_time = make_unix_date2(rdata+0);
  1116.     }
  1117.     if (a_time) {
  1118.         *a_time = make_unix_date2(rdata+4);
  1119.     }
  1120.     if (m_time) {
  1121.         *m_time = make_unix_date2(rdata+8);
  1122.     }
  1123.     if (size) {
  1124.         *size = IVAL(rdata, 12);
  1125.     }
  1126.  
  1127.     if (rdata) free(rdata);
  1128.     if (rparam) free(rparam);
  1129.     return True;
  1130. }
  1131.  
  1132. /****************************************************************************
  1133. send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
  1134. ****************************************************************************/
  1135. BOOL cli_qpathinfo2(struct cli_state *cli, char *fname, 
  1136.             time_t *c_time, time_t *a_time, time_t *m_time, 
  1137.             time_t *w_time, uint32 *size)
  1138. {
  1139.     int data_len = 0;
  1140.     int param_len = 0;
  1141.     uint16 setup = TRANSACT2_QPATHINFO;
  1142.     pstring param;
  1143.     char *rparam=NULL, *rdata=NULL;
  1144.  
  1145.     param_len = strlen(fname) + 7;
  1146.  
  1147.     memset(param, 0, param_len);
  1148.     SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
  1149.     pstrcpy(¶m[6], fname);
  1150.  
  1151.     if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
  1152.                 NULL, param, &setup, 
  1153.                 data_len, param_len, 1,
  1154.                 cli->max_xmit, 10, 0)) {
  1155.         return False;
  1156.     }
  1157.  
  1158.     if (!cli_receive_trans(cli, SMBtrans2, &data_len, ¶m_len, 
  1159.                    &rdata, &rparam)) {
  1160.         return False;
  1161.     }
  1162.  
  1163.     if (!rdata || data_len < 22) {
  1164.         return False;
  1165.     }
  1166.  
  1167.     if (c_time) {
  1168.         *c_time = interpret_long_date(rdata+0) - cli->serverzone;
  1169.     }
  1170.     if (a_time) {
  1171.         *a_time = interpret_long_date(rdata+8) - cli->serverzone;
  1172.     }
  1173.     if (m_time) {
  1174.         *m_time = interpret_long_date(rdata+16) - cli->serverzone;
  1175.     }
  1176.     if (w_time) {
  1177.         *w_time = interpret_long_date(rdata+24) - cli->serverzone;
  1178.     }
  1179.     if (size) {
  1180.         *size = IVAL(rdata, 40);
  1181.     }
  1182.  
  1183.     if (rdata) free(rdata);
  1184.     if (rparam) free(rparam);
  1185.     return True;
  1186. }
  1187.  
  1188.  
  1189. /****************************************************************************
  1190. send a qfileinfo call
  1191. ****************************************************************************/
  1192. BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
  1193.            time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
  1194. {
  1195.     int data_len = 0;
  1196.     int param_len = 0;
  1197.     uint16 setup = TRANSACT2_QFILEINFO;
  1198.     pstring param;
  1199.     char *rparam=NULL, *rdata=NULL;
  1200.  
  1201.     param_len = 4;
  1202.  
  1203.     memset(param, 0, param_len);
  1204.     SSVAL(param, 0, fnum);
  1205.     SSVAL(param, 2, SMB_INFO_STANDARD);
  1206.  
  1207.     if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0, 
  1208.                 NULL, param, &setup, 
  1209.                 data_len, param_len, 1,
  1210.                 cli->max_xmit, 2, 0)) {
  1211.         return False;
  1212.     }
  1213.  
  1214.     if (!cli_receive_trans(cli, SMBtrans2, &data_len, ¶m_len, 
  1215.                    &rdata, &rparam)) {
  1216.         return False;
  1217.     }
  1218.  
  1219.     if (!rdata || data_len < 22) {
  1220.         return False;
  1221.     }
  1222.  
  1223.     if (c_time) {
  1224.         *c_time = make_unix_date2(rdata+0);
  1225.     }
  1226.     if (a_time) {
  1227.         *a_time = make_unix_date2(rdata+4);
  1228.     }
  1229.     if (m_time) {
  1230.         *m_time = make_unix_date2(rdata+8);
  1231.     }
  1232.     if (size) {
  1233.         *size = IVAL(rdata, 12);
  1234.     }
  1235.  
  1236.     if (rdata) free(rdata);
  1237.     if (rparam) free(rparam);
  1238.     return True;
  1239. }
  1240.  
  1241. /****************************************************************************
  1242. Send a SamOEMChangePassword command
  1243. ****************************************************************************/
  1244.  
  1245. BOOL cli_oem_change_password(struct cli_state *cli, char *user, char *new_password,
  1246.                              char *old_password)
  1247. {
  1248.   char param[16+sizeof(fstring)];
  1249.   char data[532];
  1250.   char *p = param;
  1251.   fstring upper_case_old_pw;
  1252.   fstring upper_case_new_pw;
  1253.   unsigned char old_pw_hash[16];
  1254.   unsigned char new_pw_hash[16];
  1255.   int data_len;
  1256.   int param_len = 0;
  1257.   int new_pw_len = strlen(new_password);
  1258.   char *rparam = NULL;
  1259.   char *rdata = NULL;
  1260.   int rprcnt, rdrcnt;
  1261.  
  1262.   cli->error = -1;
  1263.  
  1264.   if(strlen(user) >= sizeof(fstring)-1) {
  1265.     DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
  1266.     return False;
  1267.   }
  1268.  
  1269.   if(new_pw_len > 512) {
  1270.     DEBUG(0,("cli_oem_change_password: new password for user %s is too long.\n", user));
  1271.     return False;
  1272.   }
  1273.  
  1274.   SSVAL(p,0,214); /* SamOEMChangePassword command. */
  1275.   p += 2;
  1276.   pstrcpy(p, "zsT");
  1277.   p = skip_string(p,1);
  1278.   pstrcpy(p, "B516B16");
  1279.   p = skip_string(p,1);
  1280.   fstrcpy(p,user);
  1281.   p = skip_string(p,1);
  1282.   SSVAL(p,0,532);
  1283.   p += 2;
  1284.  
  1285.   param_len = PTR_DIFF(p,param);
  1286.  
  1287.   /*
  1288.    * Now setup the data area.
  1289.    */
  1290.   memset(data, '\0', sizeof(data));
  1291.   fstrcpy( &data[512 - new_pw_len], new_password);
  1292.   SIVAL(data, 512, new_pw_len);
  1293.  
  1294.   /*
  1295.    * Get the Lanman hash of the old password, we
  1296.    * use this as the key to SamOEMHash().
  1297.    */
  1298.   memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
  1299.   fstrcpy(upper_case_old_pw, old_password);
  1300.   strupper(upper_case_old_pw);
  1301.   E_P16((uchar *)upper_case_old_pw, old_pw_hash);
  1302.  
  1303.   SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True);
  1304.  
  1305.   /* 
  1306.    * Now place the old password hash in the data.
  1307.    */
  1308.   memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
  1309.   fstrcpy(upper_case_new_pw, new_password);
  1310.   strupper(upper_case_new_pw);
  1311.  
  1312.   E_P16((uchar *)upper_case_new_pw, new_pw_hash);
  1313.  
  1314.   E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
  1315.  
  1316.   data_len = 532;
  1317.     
  1318.   if(cli_send_trans(cli,SMBtrans,PIPE_LANMAN,0,0,
  1319.                  data,param,NULL,
  1320.                  data_len , param_len,0,
  1321.                  0,2,0) == False) {
  1322.     DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
  1323.               user ));
  1324.     return False;
  1325.   }
  1326.  
  1327.   if(cli_receive_trans(cli,SMBtrans, &rdrcnt, &rprcnt, &rdata, &rparam)) {
  1328.     if(rparam)
  1329.       cli->error = SVAL(rparam,0);
  1330.   }
  1331.  
  1332.   if (rparam)
  1333.     free(rparam);
  1334.   if (rdata)
  1335.     free(rdata);
  1336.  
  1337.   return (cli->error == 0);
  1338. }
  1339.  
  1340. /****************************************************************************
  1341. send a negprot command
  1342. ****************************************************************************/
  1343. BOOL cli_negprot(struct cli_state *cli)
  1344. {
  1345.     char *p;
  1346.     int numprots;
  1347.     int plength;
  1348.  
  1349.     bzero(cli->outbuf,smb_size);
  1350.  
  1351.     /* setup the protocol strings */
  1352.     for (plength=0,numprots=0;
  1353.          prots[numprots].name && prots[numprots].prot<=cli->protocol;
  1354.          numprots++)
  1355.         plength += strlen(prots[numprots].name)+2;
  1356.     
  1357.     set_message(cli->outbuf,0,plength,True);
  1358.  
  1359.     p = smb_buf(cli->outbuf);
  1360.     for (numprots=0;
  1361.          prots[numprots].name && prots[numprots].prot<=cli->protocol;
  1362.          numprots++) {
  1363.         *p++ = 2;
  1364.         pstrcpy(p,prots[numprots].name);
  1365.         p += strlen(p) + 1;
  1366.     }
  1367.  
  1368.     CVAL(cli->outbuf,smb_com) = SMBnegprot;
  1369.     cli_setup_packet(cli);
  1370.  
  1371.     CVAL(smb_buf(cli->outbuf),0) = 2;
  1372.  
  1373.     send_smb(cli->fd,cli->outbuf);
  1374.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  1375.         return False;
  1376.  
  1377.     show_msg(cli->inbuf);
  1378.  
  1379.     if (CVAL(cli->inbuf,smb_rcls) != 0 || 
  1380.         ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
  1381.         return(False);
  1382.     }
  1383.  
  1384.     cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
  1385.  
  1386.  
  1387.     if (cli->protocol >= PROTOCOL_NT1) {    
  1388.         /* NT protocol */
  1389.         cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
  1390.         cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
  1391.         cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
  1392.         cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
  1393.         /* this time arrives in real GMT */
  1394.         cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
  1395.         memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
  1396.         if (IVAL(cli->inbuf,smb_vwv9+1) & 1)
  1397.             cli->readbraw_supported = 
  1398.                 cli->writebraw_supported = True;      
  1399.     } else if (cli->protocol >= PROTOCOL_LANMAN1) {
  1400.         cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
  1401.         cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
  1402.         cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
  1403.         cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
  1404.         /* this time is converted to GMT by make_unix_date */
  1405.         cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
  1406.         cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
  1407.         cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
  1408.         memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
  1409.     } else {
  1410.         /* the old core protocol */
  1411.         cli->sec_mode = 0;
  1412.         cli->serverzone = TimeDiff(time(NULL));
  1413.     }
  1414.  
  1415.     return True;
  1416. }
  1417.  
  1418.  
  1419. /****************************************************************************
  1420.   send a session request
  1421. ****************************************************************************/
  1422. BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
  1423.              char *myname)
  1424. {
  1425.     fstring dest;
  1426.     char *p;
  1427.     int len = 4;
  1428.     /* send a session request (RFC 1002) */
  1429.  
  1430.     fstrcpy(dest,host);
  1431.   
  1432.     p = strchr(dest,'.');
  1433.     if (p) *p = 0;
  1434.  
  1435.     fstrcpy(cli->desthost, dest);
  1436.  
  1437.     /* put in the destination name */
  1438.     p = cli->outbuf+len;
  1439.     name_mangle(dest,p,name_type);
  1440.     len += name_len(p);
  1441.  
  1442.     /* and my name */
  1443.     p = cli->outbuf+len;
  1444.     name_mangle(myname,p,0);
  1445.     len += name_len(p);
  1446.  
  1447.     /* setup the packet length */
  1448.     _smb_setlen(cli->outbuf,len);
  1449.     CVAL(cli->outbuf,0) = 0x81;
  1450.  
  1451.     send_smb(cli->fd,cli->outbuf);
  1452.     DEBUG(5,("Sent session request\n"));
  1453.  
  1454.     if (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout))
  1455.         return False;
  1456.  
  1457.     if (CVAL(cli->inbuf,0) != 0x82) {
  1458.         cli->error = CVAL(cli->inbuf,0);
  1459.         return False;
  1460.     }
  1461.     return(True);
  1462. }
  1463.  
  1464.  
  1465. /****************************************************************************
  1466. open the client sockets
  1467. ****************************************************************************/
  1468. BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip)
  1469. {
  1470.     struct in_addr dest_ip;
  1471.  
  1472.     fstrcpy(cli->desthost, host);
  1473.     
  1474.     if (!ip) {
  1475.                 if(!resolve_name( cli->desthost, &dest_ip)) {
  1476.                         return False;
  1477.                 }
  1478.     } else {
  1479.         dest_ip = *ip;
  1480.     }
  1481.  
  1482.  
  1483.     cli->fd = open_socket_out(SOCK_STREAM, &dest_ip, 139, cli->timeout);
  1484.     if (cli->fd == -1)
  1485.         return False;
  1486.  
  1487.     return True;
  1488. }
  1489.  
  1490.  
  1491. /****************************************************************************
  1492. initialise a client structure
  1493. ****************************************************************************/
  1494. BOOL cli_initialise(struct cli_state *cli)
  1495. {
  1496.     if (cli->initialised) cli_shutdown(cli);
  1497.  
  1498.     memset(cli, 0, sizeof(*cli));
  1499.     cli->fd = -1;
  1500.     cli->cnum = -1;
  1501.     cli->pid = getpid();
  1502.     cli->mid = 1;
  1503.     cli->uid = getuid();
  1504.     cli->protocol = PROTOCOL_NT1;
  1505.     cli->timeout = 20000;
  1506.     cli->bufsize = 0x10000;
  1507.     cli->max_xmit = cli->bufsize - 4;
  1508.     cli->outbuf = (char *)malloc(cli->bufsize);
  1509.     cli->inbuf = (char *)malloc(cli->bufsize);
  1510.     if (!cli->outbuf || !cli->inbuf) return False;
  1511.     cli->initialised = 1;
  1512.     return True;
  1513. }
  1514.  
  1515. /****************************************************************************
  1516. shutdown a client structure
  1517. ****************************************************************************/
  1518. void cli_shutdown(struct cli_state *cli)
  1519. {
  1520.     if (cli->outbuf) free(cli->outbuf);
  1521.     if (cli->inbuf) free(cli->inbuf);
  1522.     if (cli->fd != -1) close(cli->fd);
  1523.     memset(cli, 0, sizeof(*cli));
  1524. }
  1525.  
  1526. /****************************************************************************
  1527.   return a description of the error
  1528. ****************************************************************************/
  1529. char *cli_errstr(struct cli_state *cli)
  1530. {
  1531.     return smb_errstr(cli->inbuf);
  1532. }
  1533.  
  1534. /****************************************************************************
  1535.   return error codes for the last packet
  1536. ****************************************************************************/
  1537. void cli_error(struct cli_state *cli, int *eclass, int *num)
  1538. {
  1539.     *eclass = CVAL(cli->inbuf,smb_rcls);
  1540.     *num = SVAL(cli->inbuf,smb_err);
  1541. }
  1542.  
  1543. /****************************************************************************
  1544. set socket options on a open connection
  1545. ****************************************************************************/
  1546. void cli_sockopt(struct cli_state *cli, char *options)
  1547. {
  1548.     set_socket_options(cli->fd, options);
  1549. }
  1550.  
  1551. /****************************************************************************
  1552. set the PID to use for smb messages. Return the old pid.
  1553. ****************************************************************************/
  1554. int cli_setpid(struct cli_state *cli, int pid)
  1555. {
  1556.     int ret = cli->pid;
  1557.     cli->pid = pid;
  1558.     return ret;
  1559. }
  1560.